﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.CSharp;
using ReportQueryBuild.DataAccess;

namespace MetadataProcessor
{
    public class ClientData
    {
        private static Dictionary<string, Assembly> assemblyDictionary = new Dictionary<string, Assembly>();
        public static List<object> GetData(string query, string returnType)
        {
            List<object> data = GetData(query);

            return ConvertToReturnType(data, returnType);
        }

        private static List<object> ConvertToReturnType(List<object> dataList, string returntype)
        {
            Type returnObjectType = MetadataController.GetType(returntype);
            var properties = returnObjectType.GetProperties();
            List<object> returnList = new List<object>();
            foreach (var o in dataList)
            {
                object returnObject = MetadataController.GetInstance(returntype);
                foreach (var property in properties)
                {
                    if (property.PropertyType.IsPrimitive || property.PropertyType.Name.ToLower() == "string")
                    {
                        var propertyInfo = o.GetType().GetProperty(property.Name);
                        if (propertyInfo != null)
                        {
                            var value = propertyInfo.GetValue(o, null);
                            property.SetValue(returnObject, value, null);
                        }
                    }

                }
                returnList.Add((returnObject));
            }

            return returnList;
        }

        private static List<object> GetData(string query)
        {
            if (!assemblyDictionary.ContainsKey(query))
            {
                assemblyDictionary.Add(query, GetAssembly(query));
            }

            dynamic loObject = assemblyDictionary[query].CreateInstance("Unknown1");
            return loObject.GetData();
        }
        private static Assembly GetAssembly(string query)
        {
            ICodeCompiler loCompiler = new CSharpCodeProvider().CreateCompiler();
            CompilerParameters loParameters = new CompilerParameters();

            loParameters.ReferencedAssemblies.Add("System.dll");
            loParameters.ReferencedAssemblies.Add("System.Data.Entity.dll");
            loParameters.ReferencedAssemblies.Add("System.Core.dll");
            loParameters.ReferencedAssemblies.Add("ReportQueryBuild.DataAccess.dll");

            string lcCode =
                @"using System;                  
                  using ReportQueryBuild.DataAccess; 
                   using System.Collections.Generic;   
                  using System.Linq;  
                            public class Unknown1 
                            {
                                public IList<object> GetData()
                                {
                                    var context = new MyArchitectureDBEntities();
                                    var dev = " + query +
                                    @"return dev;
                                }
                                
                             }";

            loParameters.GenerateInMemory = false;
            CompilerResults loCompiled = loCompiler.CompileAssemblyFromSource(loParameters, lcCode);
            if (loCompiled.Errors.HasErrors)
            {
                string lcErrorMsg = "";
                lcErrorMsg = loCompiled.Errors.Count.ToString() + ") Errors:";
                for (int x = 0; x < loCompiled.Errors.Count; x++)

                    lcErrorMsg = lcErrorMsg + "\r\nLine: " +

                                 loCompiled.Errors[x].Line.ToString() + " - " +

                                 loCompiled.Errors[x].ErrorText;

                Debugger.Break();
            }



            return loCompiled.CompiledAssembly;
        }
    }
}
